/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package csci6450.chickenFriedFS.nuggetClient.threads.functions;

import csci6450.chickenFriedFS.nuggetCore.ThreadStatus;
import csci6450.chickenFriedFS.nuggetCore.Nugget;
import csci6450.chickenFriedFS.nuggetCore.NuggetConstants;
import csci6450.chickenFriedFS.nuggetCore.NuggetUtilities;
import java.io.File;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.RandomAccessFile;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author jacobschoen
 */
public class GetNuggetFromServer extends Thread {

    private Nugget nugget;
    private ThreadStatus status;
    private String fileName;

    public GetNuggetFromServer(Nugget nugget, ThreadStatus status, String fileName) {
        this.nugget = nugget;
        this.status = status;
        this.fileName = fileName;
    }

    @Override
    public void run() {
        Socket socket = null;
        try {
            System.out.println("started");
            //connect to the appropriate nugget server
            socket = new Socket(nugget.getNuggetLocation(), nugget.getNuggetServerPort());
            // open I/O streams for objects
            ObjectOutputStream outputStream = new ObjectOutputStream(socket.getOutputStream());
            ObjectInputStream inputStream = new ObjectInputStream(socket.getInputStream());
            outputStream.writeObject(NuggetConstants.GET + " " + nugget.getNuggetOffset());
            outputStream.flush();
            //the port to get the file on
            Integer port = (Integer) inputStream.readObject();
            socket.close();
            socket = null;
            //now get the nugget
            //connect to the appropriate nugget server
            socket = new Socket(nugget.getNuggetLocation(), port);
            NuggetUtilities.memCheck();
            inputStream = new ObjectInputStream(socket.getInputStream());
            //the port to get the file on
            Nugget temp = (Nugget) inputStream.readObject();
            byte[] bytes = temp.getNugget();
            byte[] swap = bytes;
            System.out.println("Buffer Start:=" + this.nugget.getBufferStart());
            if (this.nugget.getBufferStart() > 0) {
                System.out.println("Buffer Start:=" + this.nugget.getBufferStart());
                swap = new byte[temp.getBufferStart()];
                for (int i = 0; i < swap.length; i = i + 1) {
                    swap[i] = bytes[i];
                }
            }
            RandomAccessFile write = new RandomAccessFile(new File(this.fileName), "rw");
            long seek = this.nugget.getNuggetPosition() * NuggetConstants.CHUNK_SIZE;
            System.out.println("NuggetPosition :=" + this.nugget.getNuggetPosition() + " Seek :=" + seek);
            write.seek(seek);
            write.write(swap);
            write.close();
            temp = null;
            write = null;
            this.status.setSuccessful(true);
            this.status.setFinished(true);
        } catch (ClassNotFoundException ex) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex1) {
                    Logger.getLogger(GetNuggetFromServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            this.swapAndStart();
        } catch (UnknownHostException ex1) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex) {
                    Logger.getLogger(GetNuggetFromServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            this.swapAndStart();
        } catch (IOException ex) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex1) {
                    Logger.getLogger(GetNuggetFromServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            this.swapAndStart();
        } catch (Exception ex) {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex1) {
                    Logger.getLogger(GetNuggetFromServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            this.swapAndStart();
        } finally {
            if (socket != null) {
                try {
                    socket.close();
                } catch (IOException ex) {
                    Logger.getLogger(GetNuggetFromServer.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }
    }

    private void swapAndStart() {
        if (this.nugget.getNuggetRepLocation() != null) {
            System.out.println("Swap and Start called. Try Replicated spot.");
            this.nugget.setNuggetLocation(this.nugget.getNuggetRepLocation());
            this.nugget.setNuggetServerPort(this.nugget.getNuggetRepPort());
            this.nugget.setNuggetOffset(this.nugget.getRepNuggetOffset());
            this.nugget.setNuggetRepLocation(null);
            GetNuggetFromServer g = new GetNuggetFromServer(this.nugget, this.status, this.fileName);
            g.start();
        } else {
            System.out.println("Swap and Start called. But no rep.");
            this.status.setSuccessful(false);
            this.status.setFinished(true);
        }
    }
}
